package com.xique.door.project.xyl.service.impl;


import com.github.pagehelper.PageInfo;
import com.xique.common.core.constant.GenderConstants;
import com.xique.common.core.utils.*;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.door.bean.dao.HouseStatisticDAO;
import com.xique.door.bean.domain.*;
import com.xique.door.bean.dto.CompanyDTO;
import com.xique.door.bean.dto.CompanyUserCountDTO;
import com.xique.door.bean.request.company.CompanyRequest;
import com.xique.door.bean.request.company.UserCompanyRequest;
import com.xique.door.bean.request.VerifyRecordsRequest;
import com.xique.door.bean.vo.xyl.BuildingVO;
import com.xique.door.bean.vo.xyl.CompanyUserStatisticVO;
import com.xique.door.bean.vo.xyl.HouseStatisticVO;
import com.xique.door.biz.service.ICompanyBizService;
import com.xique.door.mapper.*;
import com.xique.door.project.xyl.bean.request.PersonInOutRequest;
import com.xique.door.project.xyl.bean.vo.*;
import com.xique.door.project.xyl.service.IxylService;
import com.xique.door.service.IBuildBuildingService;
import com.xique.door.service.IBuildHouseUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import java.util.List;
import java.util.Map;

/**
 * @author: caogq
 * @Date: 2021/12/20 14:54
 * @Description:
 */
@Service
public class XylServiceImpl implements IxylService {

    @Autowired
    private BuildHouseMapper buildHouseMapper;

    @Autowired
    private BuildBuildingMapper buildBuildingMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private VerifyRecordsMapper verifyRecordsMapper;

    @Autowired
    private IBuildHouseUserService buildHouseUserService;

    @Autowired
    private BuildHouseUserMapper buildHouseUserMapper;

    @Autowired
    private AreaMapper areaMapper;

    @Autowired
    private ParkInMapper parkInMapper;

    @Autowired
    private ParkCarMngtypeMapper parkCarMngtypeMapper;

    @Autowired
    private ParkCarMapper parkCarMapper;

    @Autowired
    private ICompanyBizService companyBizService;

    @Autowired
    private IBuildBuildingService buildingService;

    @Autowired
    private AliossUtil aliossUtil;


    @Override
    public AjaxResult getHomePageInfo(Long parkId) {
        XylHomePageVo xylHomePageVo = new XylHomePageVo();
        XylHomeHouseStatisticsVo houseStatistics = this.selectHomePageHouseStatistics(parkId);
        XylHomePersonStatisticsVo personStatistics = this.selectHomePagePersonStatistics(parkId);
        List<XylPersonInOutVo> personInOutVos = this.selectHomePagePersonInOutRecord(parkId);
        ParkIn parkIn = new ParkIn();
        parkIn.setParkId(parkId);
        List<XylParkInOutVo> parkInOutVos = this.selectHomePageParkInOutVos(parkIn);
        List<HouseStatisticVO> rentHouseStatistics = this.selectHomeRentHouseStatistics(parkId);
        xylHomePageVo.setRentHouseStatistics(rentHouseStatistics);
        xylHomePageVo.setHouseStatistics(houseStatistics);
        xylHomePageVo.setPersonStatistics(personStatistics);
        xylHomePageVo.setPersonInOutVos(personInOutVos);
        xylHomePageVo.setParkInOutVos(parkInOutVos);
        return AjaxResult.success(xylHomePageVo);
    }

    @Override
    public XylHomeHouseStatisticsVo selectHomePageHouseStatistics(Long parkId) {
        int totalNumber = buildHouseMapper.countParkHouseNum(parkId);
        int rentNum = buildHouseMapper.countParkRentNum(parkId);
        int singleRentNum = buildHouseMapper.countParkSingleRentNum(parkId);
        XylHomeHouseStatisticsVo houseStatistics = new XylHomeHouseStatisticsVo();
        houseStatistics.setTotalHouseNumber(totalNumber);
        houseStatistics.setEmptyHouseNumber(totalNumber - rentNum);
        houseStatistics.setRentHouseNUmber(rentNum);
        houseStatistics.setBuildingsNumber(buildBuildingMapper.countParkBuildingNum(parkId));
        houseStatistics.setSingleRentNumber(singleRentNum);
        houseStatistics.setJointRentNumber(rentNum - singleRentNum);
        return houseStatistics;
    }

    /**
     * @param parkId
     * @description: 西洋楼首页人员统计
     * @author caogq
     * @date 2021/12/22 10:51
     * @version 1.0
     */
    @Override
    public XylHomePersonStatisticsVo selectHomePagePersonStatistics(Long parkId) {
        List<User> users = userMapper.selectUserList(new User(parkId));
        long maleNumber = users.stream().filter(e -> GenderConstants.MALE.equals(e.getGender())).count();
        long feMaleNumber = users.stream().filter(e -> GenderConstants.FEMALE.equals(e.getGender())).count();
        XylHomePersonStatisticsVo personStatistics = new XylHomePersonStatisticsVo();

        personStatistics.setPersonNumber(users.size());
        personStatistics.setMaleNumber(Math.toIntExact(maleNumber));
        personStatistics.setFemaleNumber(Math.toIntExact(feMaleNumber));
        return personStatistics;
    }


    @Override
    public List<XylPersonInOutVo> selectHomePagePersonInOutRecord(Long parkId) {
        List<VerifyRecords> verifyRecords = verifyRecordsMapper.searchXylTop6VerifyRecordsList(new VerifyRecordsRequest(parkId));

        //批处理
//        List<Long> longUserIds = verifyRecords.stream().filter(e -> e.getUserId() != null).map(VerifyRecords::getUserId).collect(Collectors.toList());
//        if (CollectionUtils.isEmpty(longUserIds)) {
//            return null;
//        }
        List<XylPersonInOutVo> personInOutVos = new ArrayList<>();
        for (VerifyRecords verifyRecord : verifyRecords) {
            XylPersonInOutVo xylPersonInOutVo = new XylPersonInOutVo();
            String type = "";
            if (verifyRecord.getVisitorId() != null) {
                //类型 访客/租客
                type = "访客";
            } else if (verifyRecord.getUserId() != null) {
                type = "租客";
            } else {
                type = "外来人员";
            }

            xylPersonInOutVo.setUserName(verifyRecord.getPersonName());

            //类型 访客/租客
            xylPersonInOutVo.setType(type);
            xylPersonInOutVo.setPicUrl(verifyRecord.getPic());
            if (verifyRecord.getIdentifyTime() != null) {
                xylPersonInOutVo.setInoutDate(DateUtils.parseDateToStr(DateUtils.MM_DD_HH_MM_SS, verifyRecord.getIdentifyTime()));
            }
            personInOutVos.add(xylPersonInOutVo);
        }
        return personInOutVos;
    }

    public List<String> convertLongToStringList(List<Long> ids) {
        List<String> strIds = new ArrayList<>();
        for (Long id : ids) {
            strIds.add(String.valueOf(id));
        }
        return strIds;
    }

    @Override
    public Map<Long, Object> selectCensusRegisterByUserIds(List<Long> userIds) {
        List<User> users = userMapper.selectUserByIds(userIds, null);
        List<Long> ids = new ArrayList<>();
        for (User user : users) {
            if (user.getProvinceId() != null) {
                ids.add(user.getProvinceId());
            }
            if (user.getCityId() != null) {
                ids.add(user.getCityId());
            }
            if (user.getDistrictId() != null) {
                ids.add(user.getDistrictId());
            }
        }
        if (ids.isEmpty()) {
            return null;
        }
        List<Area> areas = areaMapper.selectTAreaByIds(ids);
        Map<Long, Object> resultMap = new HashMap<>();
        //批查询
        for (User user : users) {
            Area province = areas.stream().filter(area -> area.getAreaId().equals(user.getProvinceId())).findAny().orElse(null);
            Area city = areas.stream().filter(area -> area.getAreaId().equals(user.getCityId())).findAny().orElse(null);
            Area district = areas.stream().filter(area -> area.getAreaId().equals(user.getDistrictId())).findAny().orElse(null);
            if (province == null || city == null || district == null) {
                continue;
            }
            resultMap.put(user.getId(), province.getAreaName() + city.getAreaName() + district.getAreaName());
        }
        return resultMap;
    }

    /**
     * @param
     * @description: 西洋楼车辆统计
     * @author caogq
     * @date 2021/12/22 10:51
     * @version 1.0
     */
    @Override
    public List<XylParkInOutVo> selectHomePageParkInOutVos(ParkIn parkIn) {
        List<ParkInOut> parkInOuts = parkInMapper.selectTop6ParkInOutList(parkIn);
        if (parkInOuts.isEmpty()) {
            return new ArrayList<>();
        }
        List<Long> inMngTypeIds = parkInOuts.stream().map(ParkInOut::getInMngTypeId).collect(Collectors.toList());
        List<Long> userIds = parkInOuts.stream().filter(e -> e.getParkUserId() != null).map(ParkInOut::getParkUserId).collect(Collectors.toList());
        List<User> users = new ArrayList<>();
        if (!userIds.isEmpty()){
            users = userMapper.selectUserByIds(userIds, null);
        }


        List<ParkCarMngtype> parkCarMngtypes = parkCarMngtypeMapper.batchSelectParkCarMngtypes(inMngTypeIds, parkIn.getParkId());
        List<XylParkInOutVo> list = new ArrayList<>();
        for (ParkInOut parkInOut : parkInOuts) {
            ParkCarMngtype parkCarMngtype = parkCarMngtypes.stream().filter(e -> e.getId().equals(parkInOut.getInMngTypeId())).findAny().orElse(null);
            //车主名称
            XylParkInOutVo xylParkInOutVo = new XylParkInOutVo();
            if (!users.isEmpty()){
                User user = users.stream().filter(e -> e.getId().equals(parkInOut.getParkUserId())).findAny().orElse(null);
                xylParkInOutVo.setUserName(user.getUserName());
            }else {
                xylParkInOutVo.setUserName("未知");
            }
            xylParkInOutVo.setPlate(parkInOut.getInCarPlate());
            //管理类型
            String inMngTypeName = "";
            if (parkCarMngtype != null) {
                inMngTypeName = parkCarMngtype.getName();
            }
            xylParkInOutVo.setInMngTypeName(inMngTypeName);

            //车主类型
            if (parkInOut.getParkUserId() != null) {
                xylParkInOutVo.setType("租户");
            } else {
                xylParkInOutVo.setType("陌生人或访客");
            }


            xylParkInOutVo.setInPicUrl(aliossUtil.getXylParkGetObjectUrl(parkInOut.getInPic()).toString());
            xylParkInOutVo.setOutPicUrl(aliossUtil.getXylParkGetObjectUrl(parkInOut.getOutPic()).toString());
            if (parkInOut.getInTime()!=null){
                xylParkInOutVo.setInTime(DateUtils.parseDateToStr(DateUtils.MM_DD_HH_MM_SS, parkInOut.getInTime()));
            }
            if (parkInOut.getOutTime()!=null){
                xylParkInOutVo.setOutTime(DateUtils.parseDateToStr(DateUtils.MM_DD_HH_MM_SS, parkInOut.getOutTime()));
            }
            list.add(xylParkInOutVo);
        }
        return list;
    }

    @Override
    public AjaxResult companyPersonStatistic(Long parkId) {

        CompanyRequest companyRequest = new CompanyRequest();
        companyRequest.setParkId(parkId);
        List<CompanyDTO> companyDtos = companyBizService.getCompanyList(companyRequest);
        List<Long> companyIds = companyDtos.stream().map(CompanyDTO::getId).collect(Collectors.toList());

        UserCompanyRequest userCompanyRequest = new UserCompanyRequest();
        userCompanyRequest.setCompanyIds(companyIds);
        List<CompanyUserCountDTO> companyUserCountDtos = companyBizService.getCompanyUserCountByCompany(userCompanyRequest);
        Map<Long, Integer> companyUserCountMap = companyUserCountDtos.stream().collect(Collectors.toMap(CompanyUserCountDTO::getCompanyId, CompanyUserCountDTO::getCount));

        List<CompanyUserStatisticVO> list = OrikaUtil.converts(companyDtos, CompanyUserStatisticVO.class);
        list.forEach(item -> {
            if (StringUtils.isNull(companyUserCountMap.get(item.getId()))) {
                item.setPersonCount(0);
            } else {
                item.setPersonCount(companyUserCountMap.get(item.getId()));
            }
        });

        List<CompanyUserStatisticVO> collect = list.stream().sorted(Comparator.comparing(CompanyUserStatisticVO::getPersonCount).reversed()).collect(Collectors.toList());

        return AjaxResult.success(Collections.singletonMap("list", collect));
    }

    @Override
    public AjaxResult buildingInfo(Long parkId) {

        BuildBuilding search = new BuildBuilding();
        search.setParkId(parkId);
        List<BuildBuilding> buildings = buildingService.selectBuildBuildingList(search);

        if (buildings.isEmpty()){
            return AjaxResult.success(Collections.singletonMap("list", new ArrayList()));
        }
        List<BuildingVO> list = OrikaUtil.converts(buildings, BuildingVO.class, Collections.singletonMap("id", "buildingId"));

        return AjaxResult.success(Collections.singletonMap("list", list));
    }

    @Override
    public AjaxResult selectPagePersonInOutRecordList(PersonInOutRequest request) {
        request.setParkId(SecurityUtils.getParkId());
        List<VerifyRecords> verifyRecords = verifyRecordsMapper.searchXylVerifyRecordsList(request);

        //批处理
        List<Long> longUserIds = verifyRecords.stream().filter(e -> e.getUserId() != null).map(VerifyRecords::getUserId).collect(Collectors.toList());
        List<String> strUserIds = null;
        Map<String, Object> houseCodeMap = null;
        List<BuildHouseUser> buildHouseUsers = null;
        Map<Long, Object> censusRegisterMap = null;
        if (!CollectionUtils.isEmpty(longUserIds)) {
            strUserIds = this.convertLongToStringList(longUserIds);
            houseCodeMap = buildHouseUserService.batchSelectFreeviewHouseCodeByUserIds(strUserIds);
            buildHouseUsers = buildHouseUserMapper.batchSelectHouseUserByUserIds(strUserIds);
            censusRegisterMap = this.selectCensusRegisterByUserIds(longUserIds);
        }

        List<XylPersonInOutVo> personInOutVos = new ArrayList<>();
        for (VerifyRecords verifyRecord : verifyRecords) {
            BuildHouseUser houseuser = null;
            if (buildHouseUsers !=null){
                 houseuser = buildHouseUsers.stream().filter(e -> e.getUserId().equals(verifyRecord.getUserId())).findFirst().orElse(null);
            }
            XylPersonInOutVo xylPersonInOutVo = new XylPersonInOutVo();
            String censusRegister = "-";
            String rentDate = "-";
            String type = "";
            if (verifyRecord.getVisitorId() != null) {
                //类型 访客/租客
                type = "访客";
            } else if (censusRegisterMap != null && verifyRecord.getUserId() != null) {
                if (censusRegisterMap.get(verifyRecord.getUserId()) != null) {
                    censusRegister = String.valueOf(censusRegisterMap.get(verifyRecord.getUserId()));
                }
                if (houseuser != null && houseuser.getCheckInDate() != null && houseuser.getDueDate() != null) {
                    rentDate = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, houseuser.getCheckInDate()) + "至" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, houseuser.getDueDate());
                }
                type = "租客";
            } else {
                type = "外来人员";
            }

            xylPersonInOutVo.setUserName(verifyRecord.getPersonName());
            xylPersonInOutVo.setDeviceName(verifyRecord.getFaceSluiceName());
            //显示4位房号
            if (houseCodeMap != null && verifyRecord.getUserId() != null && houseCodeMap.get(String.valueOf(verifyRecord.getUserId())) != null) {
                Object houseCode = houseCodeMap.get(String.valueOf(verifyRecord.getUserId()));
                xylPersonInOutVo.setHouseCode(String.valueOf(houseCode));
            }

            //户籍
            xylPersonInOutVo.setCensusRegister(censusRegister);
            //出租期限
            xylPersonInOutVo.setRentDate(rentDate);
            //类型 访客/租客
            xylPersonInOutVo.setType(type);
            xylPersonInOutVo.setPicUrl(verifyRecord.getPic());
            if (verifyRecord.getIdentifyTime() != null) {
                xylPersonInOutVo.setInoutDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, verifyRecord.getIdentifyTime()));
            }
            String otype = verifyRecord.getOtype();
            if (otype == null) {
                xylPersonInOutVo.setOtype("未知");
            } else if ("1".equals(otype)) {
                xylPersonInOutVo.setOtype("刷脸");
            } else if ("21".equals(otype)) {
                xylPersonInOutVo.setOtype("刷卡");
            }
            personInOutVos.add(xylPersonInOutVo);
        }
        long total = new PageInfo(verifyRecords).getTotal();
        AjaxResult success = AjaxResult.success();
        success.put("rows", personInOutVos);
        success.put("total", total);
        return success;
    }


    /**
     * @param
     * @description: 西洋楼车辆统计
     * @author caogq
     * @date 2021/12/22 10:51
     * @version 1.0
     */
    @Override
    public AjaxResult selectPageParkInOutList(ParkIn request) {
        request.setParkId(SecurityUtils.getParkId());
        List<ParkInOut> parkInOuts = parkInMapper.selectParkInOutList(request);
        if (parkInOuts.isEmpty()){
            AjaxResult success = AjaxResult.success();
            success.put("rows", new ArrayList());
            success.put("total", 0);
            return success;
        }
        List<Long> inMngTypeIds = parkInOuts.stream().map(ParkInOut::getInMngTypeId).collect(Collectors.toList());
        List<Long> userIds = parkInOuts.stream().filter(e -> e.getParkUserId() != null).map(ParkInOut::getParkUserId).collect(Collectors.toList());
        List<User> users = new ArrayList<>();
        if (!userIds.isEmpty()){
            users = userMapper.selectUserByIds(userIds, null);
        }
        List<ParkCarMngtype> parkCarMngtypes = parkCarMngtypeMapper.batchSelectParkCarMngtypes(inMngTypeIds,request.getParkId());
        List<XylParkInOutVo> list = new ArrayList<>();
        for (ParkInOut parkInOut : parkInOuts) {
            ParkCarMngtype parkCarMngtype = parkCarMngtypes.stream().filter(e -> e.getId().equals(parkInOut.getInMngTypeId())).findAny().orElse(null);
            XylParkInOutVo xylParkInOutVo = new XylParkInOutVo();
            if (parkInOut.getParkUserId()!=null){
                User user = users.stream().filter(e -> e.getId().equals(parkInOut.getParkUserId())).findAny().orElse(null);
                xylParkInOutVo.setUserName(user.getUserName());
            }else {
                xylParkInOutVo.setUserName("未知");
            }
            xylParkInOutVo.setPlate(parkInOut.getInCarPlate());
            //管理类型
            String inMngTypeName = "";
            if (parkCarMngtype != null){
                inMngTypeName = parkCarMngtype.getName();
            }
            xylParkInOutVo.setInMngTypeName(inMngTypeName);

            //到期日
            if (parkInOut.getBeginDate() != null && parkInOut.getEndDate() != null){
                xylParkInOutVo.setDueDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,parkInOut.getBeginDate()) + "至" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,parkInOut.getEndDate()));
            }else {
                xylParkInOutVo.setDueDate("");
            }
            //车主类型
            if (parkInOut.getParkUserId() != null) {
                xylParkInOutVo.setType("租户");
            } else {
                xylParkInOutVo.setType("陌生人或访客");
            }
            xylParkInOutVo.setInPicUrl(aliossUtil.getXylParkGetObjectUrl(parkInOut.getInPic()).toString());
            xylParkInOutVo.setOutPicUrl(aliossUtil.getXylParkGetObjectUrl(parkInOut.getOutPic()).toString());
            if (parkInOut.getInTime() != null){
                xylParkInOutVo.setInTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,parkInOut.getInTime()));
            }
            if (parkInOut.getOutTime() != null){
                xylParkInOutVo.setOutTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,parkInOut.getOutTime()));
            }
            list.add(xylParkInOutVo);
        }
        long total = new PageInfo(parkInOuts).getTotal();
        AjaxResult success = AjaxResult.success();
        success.put("rows", list);
        success.put("total", total);
        return success;
    }

    @Override
    public List<ParkCarMngtype> selectParkCarMngtypeList(ParkCarMngtype parkCarMngtype) {
        return  parkCarMngtypeMapper.selectParkCarMngtypeList(parkCarMngtype);
    }

    @Override
    public List<HouseStatisticVO> selectHomeRentHouseStatistics(Long parkId) {
        List<HouseStatisticDAO> rentHousesStatistic = buildHouseMapper.selectBuildingRentHouseTop3(parkId);
        List<Long> buildingIds = rentHousesStatistic.stream().map(HouseStatisticDAO::getBuildingId).collect(Collectors.toList());
        Map<Long, String> buildingMap = buildingService.selectBuildingName(buildingIds);
        List<HouseStatisticDAO> fullHouseStatistic = buildHouseMapper.selectFullHouseStatisticByBuilding(parkId);
        List<HouseStatisticVO> houseVos = new ArrayList<>();
        for (HouseStatisticDAO rentHouse : rentHousesStatistic) {
            HouseStatisticDAO emptyHouseDao = fullHouseStatistic.stream().filter(e -> e.getBuildingId().equals(rentHouse.getBuildingId())).findAny().orElse(null);
            HouseStatisticVO houseStatisticVO = new HouseStatisticVO();
            houseStatisticVO.setBuildingId(rentHouse.getBuildingId());
            houseStatisticVO.setBuildingName(buildingMap.get(rentHouse.getBuildingId()));
            houseStatisticVO.setHouseCount(rentHouse.getHouseCount());
            houseStatisticVO.setEmptyHouseCount(emptyHouseDao.getHouseCount()-rentHouse.getHouseCount());
            houseVos.add(houseStatisticVO);
        }
        return houseVos;
    }
}
